// Copyright (C) Calum Grant 2008

#include "cppscript"
#include "dynamic/extensions.hpp"
#include "wrap_cpp_container.hpp"

#include <map>

static_call( register_pickle_type( cmp_map, map() ) );

using internal::nonroot_var;


namespace
{
	typedef nonroot_var value_type;

	struct comparator
	{
		bool operator()(const nonroot_var & a, const nonroot_var & b) const
		{
			return a.ref().impl().compare(b.ref()) == cmp_lt;
		}
	};

	struct map_traits
	{
		typedef std::pair<nonroot_var const, nonroot_var> value_type;

		typedef std::map<nonroot_var, nonroot_var, comparator, dynamic::allocator<value_type> > container;

		static var key(value_type & i) 
		{ 
			return i.first.get(); 
		}

		static var deref(value_type & i) 
		{ 
			return i.first.get(); 
		}

		static nonroot_var key(const var & v) 
		{ 
			return v;
		}

		static var value(value_type & i)
		{ 
			return i.second.get(); 
		}

		static void mark_reachable(value_type & i, gc::garbage_collector & gc)
		{
			i.first.ref().impl().mark_reachable(gc);
			i.second.ref().impl().mark_reachable(gc);
		}

		static const var_cmp_index comparison_index = cmp_map;

		static const char * class_name()
		{ 
			return "map";
		}

		static const char * iterator_class_name()
		{
			return "map::iterator";
		}
	};
}

namespace dynamic
{
	namespace types
	{
		/// Implements a map variable.
		/** \ingroup impl */
		typedef dynamic::internal::wrap_assoc_container<map_traits> map_impl;
	}
}


var dynamic::map()
{
	return new types::map_impl();
}


var dynamic::map(const var &k, const var & v)
{
	return map()(k,v);
}
